
def convert2sort(fields):
    if not fields:
        return None
    sort = list()
    for field in fields:
        if field.startswith("-"):
            field = field.lstrip("-")
            sort.append(f"{field}:desc")
        else:
            sort.append(f"{field}:asc")
    return sort


class SearchResultUtil(object):
    @staticmethod
    def extract_docs(result):
        docs = []
        for item in result["hits"]['hits']:
            source = item['_source']
            source['id'] = item['_id']
            source['score'] = item['_score']
            docs.append(source)
        return docs


class AggUtil(object):
    @staticmethod
    def terms(field, as_field, size=None):
        term_query = {as_field: {"terms": {"field": field}}}
        if size is not None:
            term_query[as_field]['terms']["size"] = size
        return term_query

    @staticmethod
    def equ_range(field, as_field, start, end, step, with_edges=True):
        """
        根据给定的范围参数，获得均分区间
        :param with_edges: if from is 10, to is 60, and with_edges is True,
                           then ranges include {"to": 10} and {"from": 60} as edge conditions
        """
        ranges = []
        for from_ in range(start, end, step):
            ranges.append({"from": from_, "to": from_ + step})
        if ranges and ranges[-1]['to'] > end:
            ranges[-1]['to'] = end
        if with_edges and ranges:
            ranges.insert(0, {"to": start})
            ranges.append({"from": end})
        range_query = {as_field: {"range": {"field": field, "ranges": ranges}}}
        return range_query

    @staticmethod
    def customized_range(field, as_field, range_, with_edges=True):
        """
        根据给定的范围参数，获得自定义区间
        :param with_edges: if from is 10, to is 60, and with_edges is True,
                           then ranges include {"to": 10} and {"from": 60} as edge conditions
        """
        if len(range_) < 2:
            raise ValueError("range_ need more than 1 items")
        ranges = []
        for i in range(len(range_)-1):
            from_, to = range_[i], range_[i+1]
            ranges.append({"from": from_, "to": to})
        if with_edges and ranges:
            ranges.insert(0, {"to": range_[0]})
            ranges.append({"from": range_[-1]})
        range_query = {as_field: {"range": {"field": field, "ranges": ranges}}}
        return range_query

    @staticmethod
    def count(field, as_field):
        return {
            as_field: {
                "value_count": {"field": field}
            }
        }

    @staticmethod
    def distinct_count(field, as_field, **kwargs):
        return {
            as_field: {
                "cardinality": {"field": field}
            }
        }

    @staticmethod
    def sum_bucket(as_field, buckets_path):
        return {
            as_field: {
                "sum_bucket": {
                    "buckets_path": buckets_path
                }
            }
        }
